﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Web;
using System.Net;
using System.Xml.Linq;
using SharpCompress.Archives;
using SharpCompress.Readers;
using System.Text.RegularExpressions;

namespace WPSJS加载项安装辅助工具ByExcel催化剂
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32.dll")]
        public extern static int GetPrivateProfileString(string segName, string keyName, string sDefault, StringBuilder buffer, int nSize, string fileName);

        [DllImport("kernel32.dll")]
        public extern static int WritePrivateProfileString(string segName, string keyName, string sValue, string fileName);


        public Form1()
        {
            InitializeComponent();
        }

        private void btnSelect7zFile_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "7z压缩文件|*.7z";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    var filePathOf7z = openFileDialog.FileName;
                    //this.txt7zFilePath.Text = filePathOf7z;

                    Setting7zPath(filePathOf7z);

                }
            }
            catch (Exception ex)
            {

                OutPutError(ex);
            }

        }

        private void Setting7zPath(string filePathOf7z, string addinUrl = "空", string addinsType = "脱机离线")
        {
            this.AddinState.ReadOnly = false;

            SharpCompress.Common.ArchiveEncoding.Default = Encoding.GetEncoding("utf-8");
            var archive = ArchiveFactory.Open(filePathOf7z);
            string jspluginsDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"kingsoft\wps\jsaddons\");
            string addinNameAndVersion = string.Empty;
            foreach (var entry in archive.Entries)
            {
                if (!entry.IsDirectory)
                {
                    if (string.IsNullOrEmpty(addinNameAndVersion))
                    {
                        addinNameAndVersion = entry.Key.Split(new char[] { '\\', '/' })[0];
                    }
                    entry.WriteToDirectory(jspluginsDir, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
                }
            }

            var addinName = Regex.Match(addinNameAndVersion, "(.+)_").Groups[1].Value;
            var matchRow = this.dataGridView1.Rows.Cast<DataGridViewRow>().FirstOrDefault(s => s.Cells[this.AddinName.Index].Value.ToString() == addinName);
            int rowIndex;
            if (matchRow != null)
            {
                rowIndex = matchRow.Index;
            }
            else
            {
                rowIndex = this.dataGridView1.Rows.Add();
            }


            var addinVersion = Regex.Match(addinNameAndVersion, ".+_(.+)$").Groups[1].Value;

            this.dataGridView1[this.AddinInstallType.Index, rowIndex].Value = addinsType;
            this.dataGridView1[this.AddinUrl.Index, rowIndex].Value = addinUrl;
            this.dataGridView1[this.AddinName.Index, rowIndex].Value = addinName;
            this.dataGridView1[this.AddinVersion.Index, rowIndex].Value = addinVersion;
            this.dataGridView1[this.AddinType.Index, rowIndex].Value = this.cmbAddinType.Text;
            this.dataGridView1[this.AddinState.Index, rowIndex].Value = true;

            //ClearOnlineItems();

            this.txtPluginsXmlPath.Text = string.Empty;
        }

        private void ClearOnlineItems()
        {
            //删除在线版
            for (int i = this.dataGridView1.Rows.Count - 1; i >= 0; i--)
            {
                if (this.dataGridView1[this.AddinInstallType.Index, i].Value.ToString() == "在线")
                {
                    this.dataGridView1.Rows.RemoveAt(i);
                }
            }
        }

        private void btnQuit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                var wpsAppDir = this.txtWpsAppDir.Text.Trim();
                var oemINIFilePath = Path.Combine(wpsAppDir, @"office6\cfgs\oem.ini");

                WritePrivateProfileString("Server", "JSPluginsServer", "", oemINIFilePath);//网络路径统一重置为空，不进行网络路径获取插件信息

                XElement xElement = new XElement("jsplugins");

                foreach (DataGridViewRow row in this.dataGridView1.Rows)
                {
                    var addinName = row.Cells[this.AddinName.Index].Value.ToString();
                    var addinType = row.Cells[this.AddinType.Index].Value.ToString();
                    var type = addinType == "表格" ? "et" : addinType == "文字" ? "wps" : "wpp";
                    var addinUrl = row.Cells[this.AddinUrl.Index].Value.ToString();
                    var addinStateOn = (bool)row.Cells[this.AddinState.Index].Value;

                    if (row.Cells[this.AddinInstallType.Index].Value.ToString() != "在线")
                    {
                        var addinVersion = row.Cells[this.AddinVersion.Index].Value.ToString();
                        XElement item;
                        if (addinStateOn)
                        {
                            item = new XElement("jsplugin",
                                            new XAttribute("name", addinName),
                                            new XAttribute("type", type),
                                            new XAttribute("url", addinUrl),
                                            new XAttribute("version", addinVersion)
                                            );
                        }
                        else
                        {
                            item = new XElement("jspluginOff",
                                            new XAttribute("name", addinName),
                                            new XAttribute("type", type),
                                            new XAttribute("url", addinUrl),
                                            new XAttribute("version", addinVersion)
                                            );
                        }
                        xElement.Add(item);
                    }
                    else
                    {
                        XElement item;
                        if (addinStateOn)
                        {
                            item = new XElement("jspluginonline",
                                            new XAttribute("name", addinName),
                                            new XAttribute("type", type),
                                            new XAttribute("url", addinUrl)
                                            );
                        }
                        else
                        {
                            item = new XElement("jspluginonlineOff",
                                            new XAttribute("name", addinName),
                                            new XAttribute("type", type),
                                            new XAttribute("url", addinUrl)
                                            );
                        }
                        xElement.Add(item);
                    }

                }

                //最终写入插件文件夹中的jsplugins.xml。
                string jspluginsXmlFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"kingsoft\wps\jsaddons\jsplugins.xml");

                File.WriteAllText(jspluginsXmlFilePath, xElement.ToString());


                WritePrivateProfileString("Support", "JsApiPlugin", "true", oemINIFilePath);

                WritePrivateProfileString("Support", "JsApiShowWebDebugger", this.chkShowWebDebugger.Checked ? "true" : "false", oemINIFilePath);

                MessageBox.Show("完成，请重新打开WPS检验安装成功与否。");
            }
            catch (Exception ex)
            {
                OutPutError(ex);
            }
        }

        private void OutPutError(Exception ex)
        {
            MessageBox.Show($"程序出错，出错原因为:{ex.Message}\n详细错误信息：\n{ex.ToString()}");
        }

        private void InialFormControls(string wpsAppDir)
        {
            var oemINIFilePath = Path.Combine(wpsAppDir, @"office6\cfgs\oem.ini");

            if (File.Exists(oemINIFilePath))
            {
                var serverUrl = GetKeyValueFromINI("Server", "JSPluginsServer", oemINIFilePath);
                if (!string.IsNullOrEmpty(serverUrl))
                {
                    //this.txtPluginsXmlPath.Text = serverUrl;

                    SettingPluginsXmlPath(serverUrl);
                }

                string jspluginsXmlFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"kingsoft\wps\jsaddons\jsplugins.xml");

                if (File.Exists(jspluginsXmlFilePath))
                {
                    var jspluginsInfoStr = File.ReadAllText(jspluginsXmlFilePath);
                    AddDgvRows(jspluginsInfoStr);
                }



                this.chkShowWebDebugger.Checked = GetKeyValueFromINI("Support", "JsApiShowWebDebugger", oemINIFilePath) == "true" ? true : false;
            }
            else
            {
                MessageBox.Show("oem.ini文件不存在，请确保WPS路径正确。仍然有问题建议重装一下。");
            }

        }

        private void SettingPluginsXmlPath(string serverUrl)
        {
            this.AddinState.ReadOnly = true;

            WebClientEx webClient = new WebClientEx(3000);
            webClient.Encoding = Encoding.UTF8;

            try
            {
                string jspluginsInfoStr = webClient.DownloadString(serverUrl);
                AddDgvRows(jspluginsInfoStr);
            }
            catch (Exception)
            {
                MessageBox.Show("下载jsplugins.xml文件失败，请确保填写的网络路径填写正确可正常访问。");
            }


        }

        private void AddDgvRows(string jspluginsInfoStr)
        {
            XElement xElement = null;
            try
            {
                xElement = XElement.Parse(jspluginsInfoStr);
            }
            catch (Exception)
            {
                MessageBox.Show("jsplugins.xml格式有误，请确保填写的网络路径对应的文件内容是正确的xml格式且可访问成功。");
                return;
            }

            //在线
            var jspluginonlines = xElement.Elements("jspluginonline");
            AddRowInfo(jspluginonlines, "在线", true);
            //在线关闭
            var jspluginonlineOffs = xElement.Elements("jspluginonlineOff");
            AddRowInfo(jspluginonlineOffs, "在线", false);

            //离线
            var jsplugins = xElement.Elements("jsplugin");
            AddRowInfo(jsplugins, "离线", true);

            //离线关闭
            var jspluginOffs = xElement.Elements("jspluginOff");
            AddRowInfo(jspluginOffs, "离线", false);

        }


        private void AddRowInfo(IEnumerable<XElement> jsplugins, string addinType, bool addinState)
        {

            foreach (var item in jsplugins)
            {
                int rowIndex;
                var name = item.Attribute("name").Value;
                var row = this.dataGridView1.Rows.Cast<DataGridViewRow>().FirstOrDefault(s => s.Cells[this.AddinName.Index].Value.ToString() == name);
                if (row != null)
                {
                    rowIndex = row.Index;
                }
                else
                {
                    rowIndex = this.dataGridView1.Rows.Add();
                }

                var url = item.Attribute("url").Value;

                var type = item.Attribute("type").Value;
                var typeName = type == "et" ? "表格" : type == "wps" ? "文字" : "演示";

                if (addinType.Contains("离线"))
                {
                    var version = item.Attribute("version").Value;
                    this.dataGridView1[this.AddinVersion.Index, rowIndex].Value = version;
                }

                this.dataGridView1[this.AddinInstallType.Index, rowIndex].Value = url == "空" ? "脱机离线" : addinType;
                this.dataGridView1[this.AddinUrl.Index, rowIndex].Value = url;
                this.dataGridView1[this.AddinName.Index, rowIndex].Value = name;
                this.dataGridView1[this.AddinType.Index, rowIndex].Value = typeName;
                this.dataGridView1[this.AddinState.Index, rowIndex].Value = addinState;
            }
        }

        private string GetKeyValueFromINI(string segName, string keyName, string oemINIFilePath)
        {
            StringBuilder sb = new StringBuilder();
            GetPrivateProfileString(segName, keyName, string.Empty, sb, 1024, oemINIFilePath);
            return sb.ToString();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                this.cmbAddinType.SelectedIndex = 0;

                var uninstallNodeOfLocalMachine = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
                var uninstallNodeOfLocalMachine32 = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);

                var uninstallNodeOfCurrentUser = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);

                var uninstallNodeOfCurrentUser32 = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);



                var appDir = GetAppDirOfWPSOffice(uninstallNodeOfCurrentUser);
                var appVersion = GetAppVersionOfWPSOffice(uninstallNodeOfCurrentUser);

                if (string.IsNullOrEmpty(appDir))
                {
                    appDir = GetAppDirOfWPSOffice(uninstallNodeOfCurrentUser32);
                    appVersion = GetAppVersionOfWPSOffice(uninstallNodeOfCurrentUser32);
                    if (string.IsNullOrEmpty(appDir))
                    {
                        appDir = GetAppDirOfWPSOffice(uninstallNodeOfLocalMachine);
                        appVersion = GetAppVersionOfWPSOffice(uninstallNodeOfLocalMachine);
                        if (string.IsNullOrEmpty(appDir))
                        {
                            appDir = GetAppDirOfWPSOffice(uninstallNodeOfLocalMachine32);
                            appVersion = GetAppVersionOfWPSOffice(uninstallNodeOfLocalMachine32);

                        }

                    }
                }

                if (!string.IsNullOrEmpty(appVersion))
                {
                    var versionsuffix = Convert.ToInt32(appVersion.Split('.')[appVersion.Split('.').Length - 1]);

                    if (appVersion.StartsWith("11.1") && versionsuffix < 10314)
                    {
                        MessageBox.Show("当前个人版WPS版本太低，请到WPS.CN官网下载新版本，卸载旧版本重新安装新版本。");
                        this.Close();
                        return;
                    }
                    else if (appVersion.StartsWith("11.8") && versionsuffix < 8808)
                    {
                        MessageBox.Show("当前企业版WPS版本太低，请到WPS.CN官网下载新版本，卸载旧版本重新安装新版本。");
                        this.Close();
                        return;
                    }
                }


                if (!string.IsNullOrEmpty(appDir))
                {
                    if (Directory.Exists(appDir))
                    {
                        InialFormControls(appDir);
                        this.txtWpsAppDir.Text = appDir;
                    }
                }
            }
            catch (Exception ex)
            {
                OutPutError(ex);
            }

        }

        private static string GetAppDirOfWPSOffice(RegistryKey registryKey)
        {

            foreach (string subKeyName in registryKey.GetSubKeyNames())
            {
                if (subKeyName == "Kingsoft Office")
                {
                    RegistryKey subKey = registryKey.OpenSubKey(subKeyName);

                    if (subKey.GetValue("LocationRoot") != null)
                    {
                        return subKey.GetValue("LocationRoot").ToString();
                    }
                    else
                    {
                        return string.Empty;
                    }
                }

            }

            return string.Empty;
        }

        private static string GetAppVersionOfWPSOffice(RegistryKey registryKey)
        {

            foreach (string subKeyName in registryKey.GetSubKeyNames())
            {
                if (subKeyName == "Kingsoft Office")
                {
                    RegistryKey subKey = registryKey.OpenSubKey(subKeyName);

                    if (subKey.GetValue("DisplayVersion") != null)
                    {
                        return subKey.GetValue("DisplayVersion").ToString();
                    }
                    else
                    {
                        return string.Empty;
                    }
                }

            }

            return string.Empty;
        }

        private void txtPluginsXmlPath_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (e.KeyChar == (char)Keys.Enter)
                {
                    string serverUrl = txtPluginsXmlPath.Text.Trim();
                    if (serverUrl.ToLower().StartsWith("http") && serverUrl.ToLower().EndsWith("jsplugins.xml"))
                    {
                        SettingPluginsXmlPath(serverUrl);
                        txtPluginsXmlPath.Text = "";
                    }
                    else if(File.Exists(serverUrl))
                    {
                        var jspluginsInfoStr = File.ReadAllText(serverUrl);
                        AddDgvRows(jspluginsInfoStr);
                        txtPluginsXmlPath.Text = "";
                    }
                   
                    e.Handled = true;
                }
            }
            catch (Exception)
            {

            }

        }


        private void txtWpsAppDir_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (e.KeyChar == (char)Keys.Enter)
                {
                    string dir = txtWpsAppDir.Text.Trim();
                    if (Directory.Exists(dir))
                    {
                        InialFormControls(dir);
                    }
                    e.Handled = true;
                }



            }
            catch (Exception)
            {

            }
        }

        private void txt7zFilePath_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (e.KeyChar == (char)Keys.Enter)
                {
                    string filePath = txt7zFilePath.Text.Trim();
                    if (filePath.ToLower().StartsWith("http"))
                    {
                        var tmpFilePath = Path.Combine(Path.GetTempPath(), "tmp.7z");
                        WebClientEx webClientEx = new WebClientEx(3000);
                        webClientEx.DownloadFile(filePath, tmpFilePath);
                        Setting7zPath(tmpFilePath, filePath, "离线");//从临时文件里解压到目标文件夹
                    }
                    else if (File.Exists(filePath))
                    {
                        Setting7zPath(filePath);
                    }
                    txt7zFilePath.Text = "";//清空路径
                    e.Handled = true;
                }

            }
            catch (Exception)
            {

            }
        }

        private void btnAddJspluginsXml_Click(object sender, EventArgs e)
        {
            try
            {
                string serverUrl = txtPluginsXmlPath.Text.Trim();

                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "JspluginsXml|*.xml";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    var filePath = openFileDialog.FileName;
                    var jspluginsInfoStr = File.ReadAllText(filePath);
                    AddDgvRows(jspluginsInfoStr);

                }

            }
            catch (Exception ex)
            {
                OutPutError(ex);
            }
        }

        private void btnOpenINI_Click(object sender, EventArgs e)
        {
            var wpsAppDir = this.txtWpsAppDir.Text.Trim();
            var oemINIFilePath = Path.Combine(wpsAppDir, @"office6\cfgs\oem.ini");
            if (File.Exists(oemINIFilePath))
            {
                System.Diagnostics.Process.Start("Explorer.exe", "/select," + oemINIFilePath);
            }

        }

        private void btnOpenPlugins_Click(object sender, EventArgs e)
        {
            string jspluginsXmlFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"kingsoft\wps\jsaddons\jsplugins.xml");

            if (File.Exists(jspluginsXmlFilePath))
            {
                System.Diagnostics.Process.Start("Explorer.exe", "/select," + jspluginsXmlFilePath);
            }
        }

        private void btnDelteAddins_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridView1.SelectedRows.Count > 0)
                {
                    foreach (DataGridViewRow row in this.dataGridView1.SelectedRows)
                    {
                        DeleteAddinDir(row.Cells[this.AddinName.Index].Value.ToString(), row.Cells[this.AddinVersion.Index].Value != null ? row.Cells[this.AddinVersion.Index].Value.ToString() : "");
                        this.dataGridView1.Rows.Remove(row);

                    }
                }
                else
                {
                    var selectRowsIndexs = this.dataGridView1.SelectedCells.Cast<DataGridViewCell>().Select(s => s.RowIndex).Distinct().ToList();

                    foreach (var rowIndex in selectRowsIndexs)
                    {
                        DeleteAddinDir(this.dataGridView1[this.AddinName.Index, rowIndex].Value.ToString(), this.dataGridView1[this.AddinVersion.Index, rowIndex].Value != null ? this.dataGridView1[this.AddinVersion.Index, rowIndex].Value.ToString() : "");
                        this.dataGridView1.Rows.RemoveAt(rowIndex);
                    }


                }

            }
            catch (Exception ex)
            {
                OutPutError(ex);
            }
        }

        private void DeleteAddinDir(string addinName, string addinVersion)
        {
            try
            {
                if (!string.IsNullOrEmpty(addinVersion))
                {
                    string jsaddonsDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"kingsoft\wps\jsaddons");
                    string addinDir = Path.Combine(jsaddonsDir, addinName + "_" + addinVersion);
                    if (Directory.Exists(addinDir))
                    {
                        Directory.Delete(addinDir, true);
                    }
                }
            }
            catch (Exception)
            {


            }


        }
    }
}
